from functools import wraps
import inspect
import time
import datetime

def cache(fn):
    class _notfoud:
        'no matched key in dict'
    paramretDict = {}#for store cache data
    sig = inspect.signature(fn)
    params = sig.parameters
    defaultDict = OrderedDict(zip(params.keys(),(value.default for value in params.values())))
    @wraps(fn)
    def wrapper(*args,**kwargs):
        _defaultDict = defaultDict.copy()
        _defaultDict.update(kwargs)
        _args = list(_defaultDict.values())
        for i,argupdate in enumerate(args):
            _args[i] = argupdate
        _args_tuple = tuple(_args)
        ret = paramretDict.get(_args_tuple,_notfoud)
        if ret is _notfoud:
            print(ret)
            print(paramretDict)
            ret = fn(*args,**kwargs)
            paramretDict[_args_tuple] = ret
            print(paramretDict) 
      
        return ret

    return wrapper


def cachetime(duration=6):
    def _cache(fn):
        def checkdel(check):
            if check is False:
                return check
            if deldict[check] <= datetime.datetime.now().timestamp():
                retdict.pop(check)
                deldict.pop(check)
                

        retdict = {}
        deldict = {}

        @wraps(fn)
        def wrapper(*args, **kwargs):

            params = inspect.signature(fn).parameters
            paramdict = {}
            paramdict.update(zip(params.keys(), args), **kwargs)
            paramdict.update(((k, params[k].default)
                              for k in (params.keys() - paramdict.keys())))
            paramtuple = tuple(sorted(paramdict.items()))
            check = list(deldict.keys())[0] if len(deldict) != 0 else False
            keys = set(retdict.keys())
            if paramtuple not in keys:
                retdict[paramtuple] = fn(*args, **kwargs)
                deltime = duration + datetime.datetime.now().timestamp()
                deldict[paramtuple] = deltime
                ret = retdict[paramtuple]
                checkdel(check)
            else:  # 这里进行较多的清除
                ret = retdict[paramtuple]
                while checkdel(check):
                    print(deldict.keys())
                    check = list(deldict.keys())[0] if len(deldict) != 0 else False
            return ret
        return wrapper
    return _cache
